/*
Plugin Name: 	jQuery.pin
https://github.com/webpop/jquery.pin
Licensed under the terms of the MIT license.
*/
(function ($) {
	"use strict";
	$.fn.pin = function (options) {
		var scrollY = 0, elements = [], disabled = false, $window = $(window);

		options = options || {};

		var recalculateLimits = function () {
			for (var i=0, len=elements.length; i<len; i++) {
				var $this = elements[i];

				if (options.minWidth && $window.width() <= options.minWidth) {
					if ($this.parent().is(".pin-wrapper")) { $this.unwrap(); }
					$this.css({width: "", left: "", top: "", position: ""});
					if (options.activeClass) { $this.removeClass(options.activeClass); }
					disabled = true;
					continue;
				} else {
					disabled = false;
				}

				var $container = options.containerSelector ? $this.closest(options.containerSelector) : $(document.body);
				var offset = $this.offset();
				var containerOffset = $container.offset();
				var parentOffset = $this.parent().offset();

				if (!$this.parent().is(".pin-wrapper")) {
					$this.wrap("<div class='pin-wrapper'>");
				}

				var pad = $.extend({
				  top: 0,
				  bottom: 0
				}, options.padding || {});

				$this.data("pin", {
					pad: pad,
					from: (options.containerSelector ? containerOffset.top : offset.top) - pad.top,
					to: containerOffset.top + $container.height() - $this.outerHeight() - pad.bottom,
					end: containerOffset.top + $container.height(),
					parentTop: parentOffset.top
				});

				$this.css({width: $this.outerWidth()});
				$this.parent().css("height", $this.outerHeight());
			}
		};

		var onScroll = function () {
			if (disabled) { return; }

			scrollY = $window.scrollTop();

			var elmts = [];
			for (var i=0, len=elements.length; i<len; i++) {          
				var $this = $(elements[i]),
					data  = $this.data("pin");

				if (!data) { // Removed element
				  continue;
				}

				elmts.push($this); 
				  
				var from = data.from - data.pad.bottom,
					to = data.to - data.pad.top;
			  
				if (from + $this.outerHeight() > data.end) {
					$this.css('position', '');
					continue;
				}
			  
				if (from < scrollY && to > scrollY) {
					!($this.css("position") == "fixed") && $this.css({
						left: $this.offset().left,
						top: data.pad.top
					}).css("position", "fixed");
					if (options.activeClass) { $this.addClass(options.activeClass); }
				} else if (scrollY >= to) {
					$this.css({
						left: "",
						top: to - data.parentTop + data.pad.top
					}).css("position", "absolute");
					if (options.activeClass) { $this.addClass(options.activeClass); }
				} else {
					$this.css({position: "", top: "", left: ""});
					if (options.activeClass) { $this.removeClass(options.activeClass); }
				}
		  }
		  elements = elmts;
		};

		var update = function () { recalculateLimits(); onScroll(); };

		this.each(function () {
			var $this = $(this), 
				data  = $(this).data('pin') || {};

			if (data && data.update) { return; }
			elements.push($this);
			$("img", this).one("load", recalculateLimits);
			data.update = update;
			$(this).data('pin', data);
		});

		$window.scroll(onScroll);
		$window.resize(function () { recalculateLimits(); });
		recalculateLimits();

		$window.on('load', update);

		return this;
	  };
})(jQuery);
